package com.swotxu.oldwebproject.redis.utils;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.SerializationException;
import org.apache.commons.lang3.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Redis 序列化统一入口
 * 提供 redis的序列化和反序列化方式。
 *
 * @Date: 2020/2/21 14:39
 * @Author: xu.hai
 */
public class RedisSerializer {
    private static final Logger logger = LoggerFactory.getLogger(RedisSerializer.class);
    /**
     * 序列化
     * 1、若实现了 Serializable接口, 则使用 JDK序列化
     * 2、若未实现了 Serializable接口，或 JDK序列化失败，使用 FastJson序列化
     * @param t
     * @param <T>
     * @return
     */
    public static <T> byte[] serialize(T t){
        if(t == null){
            return new byte[0];
        }
        if(t instanceof Serializable){
            logger.debug("Use JDK serialize!");
            try {
                return SerializationUtils.serialize((Serializable) t);
            }catch (SerializationException e){
                logger.warn("Failed to use JDK serialize! args: " + t);
            }
        }
        logger.debug("Use FastJson serialize!");
        return FastJsonRedisSerializer.serialize(t);
    }

    /**
     * 反序列化
     * 1、优先使用 JDK反序列化
     * 2、若 JDK反序列化失败，则使用 FastJson反序列化
     * @param bytes
     * @return
     */
    public static Object deserialize(byte[] bytes){
        if (ArrayUtils.isEmpty(bytes)) {
            return null;
        }
        logger.debug("Use JDK deserialize!");
        try{
            return SerializationUtils.deserialize(bytes);
        }catch (SerializationException e){
            logger.warn("Failed to use JDK deserialize!");
        }
        logger.debug("Use FastJson deserialize!");
        return FastJsonRedisSerializer.deserialize(bytes);
    }

    /**
     * 批量反序列化
     * @param bytesList
     * @return
     */
    public static List deserialize(List<byte[]> bytesList){
        return Optional.ofNullable(bytesList)
                .map(list -> list.stream().map(RedisSerializer::deserialize).collect(Collectors.toList()))
                .orElse(Collections.EMPTY_LIST);
    }

    /**
     * 将集合中每一位元素转为字节数组
     * @param arr
     * @return
     */
    public static byte[][] toBinary(String[] arr){
        byte[][] bytes = new byte[arr.length][];
        for (int i = 0; i < arr.length; i++) {
            bytes[i] = arr[i].getBytes();
        }
        return bytes;
    }
    /**
     * 将集合中每一位元素转为字节数组
     * @param map
     * @return
     */
    public static Map<byte[], byte[]> toBinary(Map<String, Object> map){
        Map<byte[], byte[]> byteMap = new HashMap<>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            byteMap.put(entry.getKey().getBytes(), serialize(entry.getValue()));
        }
        return byteMap;
    }

    /**
     * redis 使用 json序列化机制时的数据包装类
     * 如 fastJson, Gson等
     *
     * @Date: 2020/2/21 14:39
     * @Author: xu.hai
     * @param <T>
     */
    public static class RedisJsonWraper<T> {
        private T value;

        public RedisJsonWraper() {
        }

        public RedisJsonWraper(T value) {
            this.value = value;
        }
        public T getValue() {
            return value;
        }
        public void setValue(T value) {
            this.value = value;
        }
    }
}
